package msgpack

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/vmihailenco/msgpack/v5"
	"go.uber.org/zap"
	"gogogo-server/engine/cororpc"
	"gogogo-server/engine/network/codec"
	"reflect"
)

type Processor struct {
	*codec.BaseProcessor
}

type MsgWrapper struct {
	cororpc.BaseMessageArg
	SeqId uint16
}

func BuildMessage(msgId string, msg any) *MsgWrapper {
	rlt := new(MsgWrapper)
	rlt.MsgId = msgId
	rlt.Msg = msg
	return rlt
}

// UnwrapMessage 解包MsgWrapper
func UnwrapMessage[T any](anyMw any) (uint16, *T) {
	mw := anyMw.(*MsgWrapper)
	return mw.SeqId, mw.Msg.(*T)
}

func NewProcessor() *Processor {
	return &Processor{
		BaseProcessor: &codec.BaseProcessor{
			MsgInfos: make(map[any]*codec.MsgInfo),
		},
	}
}

func (p *Processor) Route(arg cororpc.IMessageArg) error {
	mw, ok := arg.(*MsgWrapper)
	if !ok {
		return errors.New(fmt.Sprintf("发送的消息:%v(%T) 不是msg wrapper", arg, arg))
	}
	mi, ok := p.MsgInfos[mw.MsgId]
	if !ok {
		return errors.New(fmt.Sprintf("发送的消息:%v(%T) 找不到转发", arg, arg))
	}
	mi.MsgCoroRPCServer.PushPTC(arg)
	return nil
}

func (p *Processor) Marshal(arg cororpc.IMessageArg) ([][]byte, error) {
	mw, ok := arg.(*MsgWrapper)
	if !ok {
		return nil, errors.New(fmt.Sprintf("msgpack只支持MsgWrapper类型,不能编码:%v(%T)", arg, arg))
	}
	t, ok := arg.GetMsgId().(string)
	if !ok {
		return nil, errors.New("第一个参数需要是协议名字")
	}
	var bw bytes.Buffer
	lnName := uint8(len(t))
	binary.Write(&bw, binary.LittleEndian, lnName)
	bw.Write([]byte(t))
	binary.Write(&bw, binary.LittleEndian, mw.SeqId)
	b, e := msgpack.Marshal(arg.GetMsg)
	if e != nil {
		return nil, errors.New(fmt.Sprintf("序列化:%v 出错", arg.GetMsg()))
	}
	bw.Write(b)
	return [][]byte{[]byte(bw.String())}, nil
}

func (p *Processor) Unmarshal(data []byte) (cororpc.IMessageArg, error) {
	if len(data) < 4 {
		return nil, errors.New("长度非法")
	}
	nameLen := int(data[0])
	if len(data) < nameLen+3 {
		return nil, errors.New(fmt.Sprintf("长度非法,小于%d", nameLen+3))
	}
	msgId := string(data[1 : nameLen+1])
	mi, ok := p.MsgInfos[msgId]
	if !ok {
		return nil, errors.New(fmt.Sprintf("消息：%s 未注册", msgId))
	}
	mw := &MsgWrapper{}
	mw.SeqId = binary.LittleEndian.Uint16(data[nameLen+1 : nameLen+3])
	mw.MsgId = msgId
	mw.Msg = reflect.New(mi.MsgType.Elem()).Interface()
	if e := msgpack.Unmarshal(data[nameLen+3:], &mw.Msg); e != nil {
		return nil, e
	}
	return mw, nil
}
func (p *Processor) RegisterRouter(args ...any) {
	if len(args) < 3 {
		zap.S().Fatalf("注册路由需要3个参数,只传了:%d(%s)", len(args), args)
		return
	}
	msgId, ok := args[0].(string)
	if !ok {
		zap.S().Fatalf("msgid:%v(%T) 注册失败,不是string类型", args[0], args[0])
	}
	var msgType reflect.Type = nil
	if args[1] != nil {
		msgType = reflect.TypeOf(args[1])
	}
	corpc, ok := args[2].(*cororpc.RPCServer)
	if !ok {
		zap.S().Fatalf("消息:%s 第3个参数要是*cororpc.RPCServer", args[0])
	}
	p.MsgInfos[msgId] = &codec.MsgInfo{
		MsgType:          msgType,
		MsgCoroRPCServer: corpc,
	}
}
